﻿using HsServerHa.Common.Auth;
using HsServerHa.Entity.Models;
using HsServerHa.Utility.SQLite;
using Quartz;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace HsServerHa.Jobs
{
    [DisallowConcurrentExecution]
    public class CheckFilesSyncTaskNewJob : IJob
    {
        
        public static List<FileSystemWatcher> fileSystemWatcherList = new List<FileSystemWatcher>();
        public static List<FilesSyncManageEntity> filesSyncManageList = new List<FilesSyncManageEntity>();
        public async Task Execute(IJobExecutionContext context)
        {
            #region 授权验证
            if (!AuthorizationVerification.IsVerification())
            {
                return;
            }
            #endregion 
            if (App.isMaster!=null)
            {
           
                var listXt = await SQLiteHelper.TableAsync<HeartEntity>().Where(x => x.IsLocal == "true").ToListAsync().ConfigureAwait(false);
                var xtFirst = listXt?.FirstOrDefault();
                if (App.isMaster.Value)
                { 
                    if (xtFirst?.MasterHeartIPBind==null)
                    {
                        return;
                    }
                    await CreateFileListenServer().ConfigureAwait(false);
                    //主机使用FTP客户端同步文件
                    await MasterSyncFiles().ConfigureAwait(false);
                    if (App.IsStartSync)
                    {
                        return;
                    }
                    // 设置从服务器IP地址和端口号
                    IPAddress backupServerIpAddress = IPAddress.Parse(xtFirst.HeartIP);
                    int backupServerPort = (ConfigurationManager.AppSettings["FilePort"]?.ToString() ?? "6602").ToInt(); ;

                    // 创建监听Socket
                    TcpListener listener = new TcpListener(backupServerIpAddress, backupServerPort);
                    listener.Start();

                    App.IsStartSync = true;
                    App.fileTcpClient= listener.AcceptTcpClient();
                    Console.WriteLine("Waiting for backup server to connect...");

                   
                }
                else
                {
                    if (xtFirst == null)
                    {
                        return;
                    }
                    if (App.IsStartSync)
                    {
                        return;
                    }
                    try
                    {
                        // 设置主服务器IP地址和端口号
                        IPAddress remoteIpAddress = IPAddress.Parse(xtFirst.MasterHeartIPBind);
                        int remotePort = (ConfigurationManager.AppSettings["FilePort"]?.ToString() ?? "6602").ToInt(); ;

                        // 创建客户端Socket并连接到主服务器
                        App.fileTcpClient = new TcpClient();
                        App.fileTcpClient.Connect(remoteIpAddress, remotePort);
                        App.IsStartSync = true; 
                        //实际接收到的字节数 

                        while (true)
                        {
                            try
                            {
                                NetworkStream backupNetworkStream = App.fileTcpClient.GetStream();

                                // 读取要备份的文件信息
                                byte[] fileInfoBuffer = new byte[1024];
                                int fileInfoBytesRead = backupNetworkStream.Read(fileInfoBuffer, 0, fileInfoBuffer.Length);
                                string fileInfo = System.Text.Encoding.UTF8.GetString(fileInfoBuffer, 0, fileInfoBytesRead);
                                string[] fileDetails = fileInfo.Split(',');
                                string action = fileDetails[0];
                                string filePath = fileDetails[1];

                                // 处理文件备份操作
                                if (action == "Created" || action == "Changed")
                                {
                                    // 读取文件内容并保存到本地
                                    using (FileStream fileStream = File.Create(filePath))
                                    {
                                        byte[] buffer = new byte[1024];
                                        int bytesRead;
                                        while ((bytesRead = backupNetworkStream.Read(buffer, 0, buffer.Length)) > 0)
                                        {
                                            fileStream.Write(buffer, 0, bytesRead);
                                            bytesRead = 0;
                                        }
                                    }

                                    Console.WriteLine("File backed up successfully.");
                                }
                                else if (action == "RENAME")
                                {
                                    string[] names = fileInfo.Split('|');
                                    string originalFileName = names[0];
                                    string newFileName = names[1];
                                    File.Move(originalFileName, newFileName);
                                    //byte[] buffer = Encoding.UTF8.GetBytes(renameInfo);
                                    //client.Send(buffer);
                                }
                                else if (action == "Deleted")
                                {
                                    // 删除本地文件
                                    File.Delete(filePath);
                                    Console.WriteLine("File deleted successfully.");
                                }
                            }
                            catch (Exception ex)
                            {

                            }


                            // 关闭连接
                            //backupClient.Close();
                            //listener.Stop();
                        }
                    }
                    catch (Exception ex)
                    {
                        if (App.fileTcpClient!=null)
                        {
                            App.fileTcpClient.Dispose();
                            App.fileTcpClient = null;
                        }
                    }
                 
                }
            }
        }

        /// <summary>
        /// 主机做文件同步操作
        /// </summary>
        /// <returns></returns>
        public static async Task MasterSyncFiles() {
            try
            {
                foreach (var item in filesSyncManageList)
                {
                    var key = item.ProgramKey;
                    var timer = item.Delayed.ToInt();
                    var Date = DateTime.Now.AddSeconds(-timer);
                    //查询同步文件
                    var fileList = await SQLiteHelper.TableAsync<FilesTargetManageEntity>().Where(x => x.ProgramKey == key &&x.CreateTime <= Date).ToListAsync();
                    foreach (var file in fileList)
                    {
                       await Task.Run(async () => {
                           try
                           {
                               await SendFileInfoToMainServer(file.TypeName, file.SourceFilePath).ConfigureAwait(false);
                               //删除数据库
                               SQLiteHelper.ExecuteSql($"delete from FilesTargetManage where  and Name='{file.Name}' and TargetFilePath='{file.TargetFilePath}'");
                           }
                           catch (Exception ex)
                           {
                               LoggerHelper.Error(ex.Message,"文件同步");
                           }
                         
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                 
            }
        
        }

        /// <summary>
        /// 创建文件监听服务
        /// </summary>
        /// <returns></returns>
        public static async Task CreateFileListenServer()
        {
            var list = await SQLiteHelper.TableAsync<FilesSyncManageEntity>().ToListAsync().ConfigureAwait(false);
            filesSyncManageList=list;
            foreach (var item in list)
            {
                foreach (var file in fileSystemWatcherList)
                {
                    if (item.IsEnable == "是")
                    {
                        if (item.FilePath == file.Path)
                        {
                            continue;
                        }
                        else
                        {
                            string sourceDirectory = $@"{item.FilePath}";
                            FileSystemWatcher watcher = new FileSystemWatcher();
                            watcher.Path = sourceDirectory;

                            // 监控文件的改变类型
                            watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

                            // 添加事件处理程序
                            watcher.Changed += OnChanged;
                            watcher.Created += OnChanged;
                            watcher.Deleted += OnChanged;
                            watcher.Renamed += OnRenamed;

                            // 开始监控
                            watcher.EnableRaisingEvents = true;
                            fileSystemWatcherList.Add(watcher);
                        }
                    }
                    else
                    {
                        foreach (var watcher in fileSystemWatcherList)
                        {
                            watcher.EnableRaisingEvents = false;
                        }
                    }

                }
                if (!fileSystemWatcherList.Any(x => x.Path == item.FilePath && item.IsEnable == "是"))
                {
                    string sourceDirectory = $@"{item.FilePath}";
                    FileSystemWatcher watcher = new FileSystemWatcher();
                    watcher.Path = sourceDirectory;

                    // 监控文件的改变类型
                    watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName;

                    // 添加事件处理程序
                    watcher.Changed += OnChanged;
                    watcher.Created += OnChanged;
                    watcher.Deleted += OnChanged;
                    watcher.Renamed += OnRenamed;

                    // 开始监控
                    watcher.EnableRaisingEvents = true;
                    fileSystemWatcherList.Add(watcher);
                }
                if (item.IsEnable == "否")
                {
                    fileSystemWatcherList.RemoveAll(x => x.Path == item.FilePath);
                }
            }
            fileSystemWatcherList.RemoveAll(x => x.EnableRaisingEvents == false);
        }

        /// <summary>
        /// 文件增删改
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private static void OnChanged(object source, FileSystemEventArgs e)
        {
            FileSystemWatcher watcher= source as FileSystemWatcher;

            // 获取文件操作类型
            string action = e.ChangeType.ToString();

            // 获取文件路径
            string filePath = e.FullPath;

            SQLiteHelper.ExecuteSql($"delete from FilesTargetManage where ProgramKey='{filesSyncManageList.FirstOrDefault(x => x.FilePath == watcher.Path)?.ProgramKey}' and Name='{e.Name}' and TargetFilePath='{filePath}'");

            //SendFileInfoToMainServer(action,filePath);
            FilesTargetManageEntity entity = new FilesTargetManageEntity() { 
                TypeName = action,
                TargetFilePath = filePath,
                SourceFilePath = filePath,
                Name=e.Name,
                ProgramKey= filesSyncManageList.FirstOrDefault(x=>x.FilePath==watcher.Path)?.ProgramKey,
                CreateTime = DateTime.Now
            };
            SQLiteHelper.Add(entity);
        }

        /// <summary>
        /// 当文件被重命名时触发
        /// </summary>
        /// <param name="source"></param>
        /// <param name="e"></param>
        private static void OnRenamed(object source, RenamedEventArgs e)
        {
            FileSystemWatcher watcher = source as FileSystemWatcher;
            // 获取文件操作类型
            string action = "RENAME";

            // 获取文件路径
            string filePath = e.FullPath;
            string oldFilePath = e.OldFullPath;
            string renameInfo = oldFilePath + "|" + filePath;
            //SendFileInfoToMainServer(action, renameInfo);
            SQLiteHelper.ExecuteSql($"delete from FilesTargetManage where ProgramKey='{filesSyncManageList.FirstOrDefault(x => x.FilePath == watcher.Path)?.ProgramKey}' and Name='{e.Name}' and TargetFilePath='{renameInfo}'");

            FilesTargetManageEntity entity = new FilesTargetManageEntity()
            {
                TypeName = action,
                TargetFilePath = renameInfo,
                SourceFilePath = renameInfo,
                Name = e.Name,
                ProgramKey = filesSyncManageList.FirstOrDefault(x => x.FilePath == watcher.Path)?.ProgramKey,
                CreateTime =DateTime .Now
            };
            SQLiteHelper.Add(entity);
        }

         
        // 发送文件信息到主服务器
        private static async Task SendFileInfoToMainServer(string action, string filePath)
        {
            try
            {
                if (App.fileTcpClient == null)
                {
                    throw new Exception("TCP未连接");
                }
                // 将文件操作类型和文件路径组合成字符串
                string fileInfo = action + "," + filePath;

                // 将文件信息转换为字节数组并发送到主服务器
                byte[] fileInfoBuffer = System.Text.Encoding.UTF8.GetBytes(fileInfo);
                NetworkStream networkStream = App.fileTcpClient.GetStream();
                networkStream.Write(fileInfoBuffer, 0, fileInfoBuffer.Length);

                // 如果是新增、修改或重命名操作，则发送文件内容到主服务器
                if (action == "Created" || action == "Changed")
                {
                    using (FileStream fileStream = File.OpenRead(filePath))
                    {
                        byte[] buffer = new byte[1024];
                        int bytesRead;
                        while ((bytesRead = fileStream.Read(buffer, 0, buffer.Length)) > 0)
                        {
                            networkStream.Write(buffer, 0, bytesRead);
                        }
                    }
                }

                Console.WriteLine("File information sent to the main server.");
         

            }
            catch (Exception ex)
            {
                throw;
            }
        
        }
    }
}
